package com.dapeng.cleardatabackend.exception;

import com.dapeng.cleardatabackend.common.BaseResponse;
import com.dapeng.cleardatabackend.common.ErrorCode;
import com.dapeng.cleardatabackend.common.ResultUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.transaction.TransactionTimedOutException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

/**
 * @author dapeng
 * @description 全局异常处理器
 * @date 2023/11/12 20:32
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 自定义的业务异常处理程序
     *
     * @param e e
     * @return {@link BaseResponse }<{@link Void }>
     */
    @ExceptionHandler(BusinessException.class)
    public BaseResponse<Void> businessExceptionHandler(BusinessException e) {
        log.error("businessException:" + e.getMessage(), e);
        return ResultUtils.error(e.getCode(), e.getMessage());
    }


    /**
     * 处理http消息不可读，主要是请求体错误
     *
     * @param e e
     * @return {@link BaseResponse }<{@link Void }>
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public BaseResponse<Void> handleHttpMessageNotReadable(HttpMessageNotReadableException e) {
        log.error("handleHttpMessageNotReadable", e);
        return ResultUtils.error(ErrorCode.PARAMS_ERROR.getCode(), "请求体错误");
    }

    /**
     * 方法参数是否有效异常处理程序
     *
     * @param e e
     * @return {@link BaseResponse }<{@link Void }>
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public BaseResponse<Void> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        log.error("methodArgumentNotValidException", e);
        StringBuilder sb = new StringBuilder();
        e.getBindingResult().getAllErrors().forEach(error -> {
            sb.append(error.getDefaultMessage()).append(";");
        });
        sb.deleteCharAt(sb.length() - 1);
        return ResultUtils.error(ErrorCode.PARAMS_ERROR, sb.toString());
    }

    /**
     * 方法参数类型不匹配异常处理程序
     *
     * @param e e
     * @return {@link BaseResponse }<{@link Void }>
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public BaseResponse<Void> methodArgumentTypeMismatchExceptionHandler(MethodArgumentTypeMismatchException e) {
        log.error("MethodArgumentTypeMismatchException", e);
        return ResultUtils.error(ErrorCode.PARAMS_ERROR);
    }

    /**
     * 绑定异常处理程序
     *
     * @param e e
     * @return {@link BaseResponse }<{@link Void }>
     */
    @ExceptionHandler(BindException.class)
    public BaseResponse<Void> bindExceptionHandler(BindException e) {
        log.error("BindException", e);
        StringBuilder sb = new StringBuilder();
        e.getBindingResult().getAllErrors().forEach(error -> {
            sb.append(error.getDefaultMessage()).append(";");
        });
        sb.deleteCharAt(sb.length() - 1);
        return ResultUtils.error(ErrorCode.PARAMS_ERROR, sb.toString());
    }

    /**
     * 事务超时异常处理程序
     *
     * @param e e
     * @return {@link BaseResponse }<{@link Void }>
     */
    @ExceptionHandler(TransactionTimedOutException.class)
    public BaseResponse<Void> transactionTimedOutExceptionHandler(TransactionTimedOutException e) {
        log.error("TransactionTimedOutException", e);
        return ResultUtils.error(ErrorCode.OPERATION_ERROR, "处理超时");
    }

    /**
     * 异常处理程序
     *
     * @param e e
     * @return {@link BaseResponse }<{@link Void }>
     */
    @ExceptionHandler(Exception.class)
    public BaseResponse<Void> runtimeExceptionHandler(RuntimeException e) {
        log.error("Exception", e);
        return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "服务器内部错误");
    }
}
